# -*- coding: utf-8 -*-
"""
Created on Thu Jul 12 22:42:26 2018

@author: Administrator
"""
#%%
import os
import pandas as pd
import numpy as np
from  scipy.stats import pearsonr


from agilepipe.plot.seaborn import Boxplot
from agilepipe.plot.seaborn import Juxtaposed_barplot
from agilepipe.plot.matplotlib import Figure_multiaxe,Figure_gridspec,Axe_bar,Axe_legend,Axe_scatter

#import stac
#%%

class Basic_const(object):
  
  #需要被分析的excel的column name
  first_modality_rm = '1st_modality_rm'
  second_modality_rm = '2nd_modality_rm'
  p_coeff = 'p_coeff'
  p_pvalue = 'p_pvalue'
  p_coeff_fishz = 'p_coeff_fishz'
  s_coeff = 's_coeff'
  s_pvalue = 's_pvalue' 
  s_coeff_fishz = 's_coeff_fishz'
  voxelNUM = 'voxelNUM'
  subj = 'subjectID'
  modality = 'modality'  
  region = 'region'
  GM_Probability = 'GM_Probability'

  #friedman_df的column name	
  F_value = 'F_value'
  P_value = 'P_value'
  rankings = 'rankings'
  pivots = 'pivots'
  friedman_column = [F_value,P_value,rankings,pivots]
  
  mean_std = 'mean_std'
  underline = '_'
  linkline = '-'
  xlsx_str = '.xlsx'
  tiff_str = '.tiff'
  across_spatial_str = 'across_spatial'
  jpeg = '.jpeg'
  svg = 'svg'
  dotsvg = '.svg'
  xlsx = 'xlsx'
  dotxlsx = '.xlsx'
  
  zero_numb = 0 #用于从ax_arrayp[][]取出一个ax
  one_numb = 1

  coeff = '_coeff'
  pvalue = '_pvalue'
  
  bar_color_list = ['#539caf']
  error_color_list = ['#000000']  
  color_list = ['#FF0033','#006699','#FFCC00','#009999','#CC3366','#CCCC00','#666666']
  label_list = ['PETvsCBF','PETvsfALFF','PETvsReHo','PETvsDC','CBFvsfALFF','CBFvsReHo','CBFvsDC']

class Basic_method(object):
  def construct_column_list(self,list):
    print('Basic_method,list:',list)
    column_list = []
    for item in list:
      item = str(item)
      print('item+self.coeff:',item+self.coeff)
      column_list = column_list + [item+self.coeff,item+self.pvalue]
    return column_list

#%%

class Mstd(Basic_const):
  def __init__(self,in_df,dvar,idvar,modality):
    self.out_df = pd.DataFrame(index=[modality],columns=in_df[idvar].unique())
    for column_name in self.out_df.columns:
      self.out_df[column_name][modality]  = str('%.2f' % in_df[in_df[idvar] == column_name][dvar].mean()) + '±' +\
                                            str('%.2f' % in_df[in_df[idvar] == column_name][dvar].std())
    print(self.out_df)

#class ANOVARM(Basic_const):
#  def __init__(self,in_df,dvar,idvar):
#    level_list = in_df[idvar].unique()
#    samples = ''.join([in_df[in_df[idvar]==i] for i in level_list])
#    self.results = eval('stac.nonparametric_tests.friedman_test(' + samples +')')

#class Friedman(Basic_const):
#  def __init__(self,in_df,dvar,idvar):
#    level_list = in_df[idvar].unique()
#    samples = ''.join([in_df[in_df[idvar]==i] for i in level_list])
#    self.group_results = eval('stac.nonparametric_tests.friedman_test(' + samples +')')


#%%

class Summarize(Basic_const):

  def __init__(self,excel_filepath):
    
    output_dirpath = os.path.split(excel_filepath)[0]
    coeff_df = pd.read_excel(excel_filepath)
    GM_P_list = coeff_df[self.GM_Probability].unique()
    
    for GM_P in GM_P_list:
      print('GM_P:', GM_P)
      GM_P_df = coeff_df[ coeff_df[self.GM_Probability]==GM_P ]

      for i in [self.first_modality_rm,self.second_modality_rm,self.p_coeff,self.s_coeff]:
        print('i:',i)
        modality_list = GM_P_df[self.modality].unique()
        
#        #下面进行 Friedman检验
#        friedman_df = pd.DataFrame(index=modality_list,columns=self.friedman_column)
#        friedman = Friedman(GM_P_df,i,self.region)
#        friedman.group_results
        
        #下面这mstd_out_df mstd_output_filepath主要是为Mstd这个类准备的。
        mstd_out_df = pd.DataFrame(columns = GM_P_df[self.region].unique())
        print('mstd_out_df:',mstd_out_df )
        mstd_output_filepath = output_dirpath + os.sep + self.across_spatial_str + self.linkline + GM_P + self.linkline + \
                                i + self.linkline + self.mean_std + self.xlsx_str
        print('mstd_output_filepath:',mstd_output_filepath)
        for k in modality_list:
          print('k:',k)
          md_GM_P_df = GM_P_df[GM_P_df[self.modality]==k]
          #计算每个i列的mean std
          mstd = Mstd(md_GM_P_df,i,self.region,k)
          mstd_out_df = mstd_out_df.append(mstd.out_df)
          #画每个i列的箱型图
          box_output_filepath = output_dirpath + os.sep + GM_P+self.linkline + k + self.linkline + i + self.tiff_str
          Boxplot(md_GM_P_df,i,self.region,box_output_filepath)
        print('before mstd_out_df')
        mstd_out_df.to_excel(mstd_output_filepath,index=True)
        print('after mstd_out_df')


#%%
#
class Rearrange(Basic_const):
  def __init__(self,rg_excel_filepath,gm_excel_filepath,output_dirpath):
    #rg_excel_filepath中rg是region的简写
    #gm是grey matter的缩写
    rg_coeff_df = pd.read_excel(rg_excel_filepath)
    gm_coeff_df = pd.read_excel(gm_excel_filepath)
    
    #下面gmp是GM_Probability的简写
    rg_gmp_list = rg_coeff_df[self.GM_Probability].unique()
    
    gm_gmp_list = gm_coeff_df[self.GM_Probability].unique()
    print('gm_gmp_list:',gm_gmp_list)

    for rg_gmp_item in rg_gmp_list:
      print('rg_gmp_item:',rg_gmp_item)
      #下面的gmp是grey matter probability的缩写。
      gmp_rg_coeff_df = rg_coeff_df[rg_coeff_df[self.GM_Probability]==rg_gmp_item ]
      
      gm_gmp_item = self.get_correspond(rg_gmp_item,gm_gmp_list)
      print('gm_gmp_item:',gm_gmp_item)
      gmp_gm_coeff_df = gm_coeff_df[gm_coeff_df[self.GM_Probability]==gm_gmp_item ]
      print('gmp_gm_coeff_df:',gmp_gm_coeff_df)
      
      for column_name_str in [self.first_modality_rm,self.second_modality_rm,self.p_coeff,self.p_coeff_fishz,\
                              self.s_coeff,self.s_coeff_fishz]:
        print('column_name_str:',column_name_str)
        modality_list = gmp_rg_coeff_df[self.modality].unique()
        #gmp_rg_coeff_df   gmp_gm_coeff_df这两个df的modality_list是一致的。
        for  modality_item in modality_list:
          print('modality_item:',modality_item )
          #下面的md是modality的缩写，md_gmp_rg_coeff_df表示gmp_rg_coeff_df在modality这一列中提取出等于modality_item部分
          md_gmp_rg_coeff_df = gmp_rg_coeff_df[gmp_rg_coeff_df[self.modality] == modality_item]
          md_gmp_gm_coeff_df = gmp_gm_coeff_df[gmp_gm_coeff_df[self.modality] == modality_item]
          print('md_gmp_gm_coeff_df:',md_gmp_gm_coeff_df)
          
          #下面md_gmp_rg_coeff_df[self.region]有多个值（每一个值表示一个脑区mask）
          #而md_gmp_gm_coeff_df[self.region]只有一个值，即灰质mask
          rg_region_list = md_gmp_rg_coeff_df[self.region].unique()
          gm_region = md_gmp_gm_coeff_df[self.region].unique()[0]
          print('gm_region:',gm_region)
          
          for rg_region_item in rg_region_list:
            print('rg_region_item:',rg_region_item)
            #下面的rg是region的缩写，rg_md_gmp_rg_coeff_df表示md_gmp_rg_coeff_df在region这一列中提取出
            #等于rg_region_list这一列            
            rg_md_gmp_rg_coeff_df = md_gmp_rg_coeff_df[md_gmp_rg_coeff_df[self.region]==rg_region_item]
            rg_md_gmp_gm_coeff_df = md_gmp_gm_coeff_df[md_gmp_gm_coeff_df[self.region]==gm_region]
            print('rg_md_gmp_rg_coeff_df:',rg_md_gmp_rg_coeff_df)
            print('rg_md_gmp_gm_coeff_df:',rg_md_gmp_gm_coeff_df)
            
            output_filepath = output_dirpath + os.sep + rg_gmp_item + self.linkline + column_name_str + self.linkline +\
                              modality_item + self.linkline + rg_region_item  + self.jpeg
            print('output_filepath:',output_filepath)
            
            Juxtaposed_barplot(rg_md_gmp_rg_coeff_df[column_name_str],rg_md_gmp_gm_coeff_df[column_name_str],\
                              modality_item + ' '+column_name_str, [rg_region_item,gm_region] ,output_filepath)
            
            
  @staticmethod
  def get_correspond(rg_gmp_item,gm_gmp_list):
      gm_gmp_item_index = [i in rg_gmp_item for i in gm_gmp_list].index(1)
      return gm_gmp_list[gm_gmp_item_index]
      
    
#%%

class Across_regionvoxel_summarize(Basic_const):
  
  x_label_str = ''
  y_label_str = 'Correlation'
  eponymous = 'Across_regionvoxel_summarize'
  
  def __init__(self,input_filepath,figsize_tuple,column_numb,barwidth,spacing,style,major_locator,output_dirpath):
    #为读取input_filepath
    df = pd.read_excel(input_filepath)
    #根据读取的df准备必要的参数
    region_list = df[self.region].unique()
    axe_numb = len(region_list)
    print('axe_numb:',axe_numb)
    modality_list = df[self.modality].unique()
    #下面是构造输出文件路径。
    svg_output_filepath = output_dirpath + os.sep + self.eponymous + self.dotsvg     
    print('svg_output_filepath:',svg_output_filepath)
    excel_output_filepath =  output_dirpath + os.sep + self.eponymous + self.dotxlsx
    print('excel_output_filepath:',excel_output_filepath)
    
    
    #生成fig axe_array用于plot
    fig,axe_array = Figure_multiaxe.multiaxe(figsize_tuple,axe_numb,column_numb,style)
    #构造一个df用于存放mean std值
    mean_std_df = pd.DataFrame(index=modality_list,columns=region_list)   
    
    #下面每一个region_item占一个axe，每一个modality_item占某一个axe内的一个bar
    i = 0
    for region_item in region_list:
      print('region_item:',region_item)
      #下面将df属于region_item的那一部分取出
      region_item_df = df[df[self.region]==region_item]
      x_data = np.arange(len(modality_list)) * spacing
      y_data = []  #需要在循环中给予赋值
      error_data = []   #需要在循环中给予赋值
      title = region_item
      #下面开始按照modality_item循环，以收集y_data和error_data
      j = 0
      for modality_item in modality_list:
        print('modality_item:',modality_item)
        #agent是一个中间变量
        agent = region_item_df[region_item_df[self.modality]==modality_item][self.p_coeff]
        mean = '%.2f'%agent.mean()
        std = '%.2f'%agent.std()
        y_data.append(float(mean))
        error_data.append(float(std))
        
        mean_std_df[region_item][modality_item] = mean + '±' + std
        j = j + 1

      Axe_bar.axe(axe_array[i][self.zero_numb],x_data, y_data, error_data, self.x_label_str, self.y_label_str, title,\
               self.color_list,barwidth,self.error_color_list[0],[],major_locator)
      i = i + 1

    Axe_legend.axe(axe_array[len(axe_array)-1][self.zero_numb],self.color_list,modality_list)
    fig.savefig(svg_output_filepath,format=self.svg)
    mean_std_df.to_excel(excel_output_filepath)

#%%

class Across_region_summarize(Basic_const):

  x_label_str = ''
  y_label_str = 'Correlation'
  title_str = 'Across region correlation'
  eponymous  = 'Across_region_summarize'
  mean_str = 'mean'
  std_str = 'std'
  groupmean_coeff = 'groupmean_coeff' 
  groupmean_pvalue = 'groupmean_pvalue'
  pet_falff = 'PETvsfALFF'
  pet_reho = 'PETvsReHo'
  def __init__(self,input_filepath,figsize_tuple,barwidth,spacing,style,major_locator,output_dirpath):
    #读取input_filepath
    df = pd.read_excel(input_filepath)
    #利用读取的df准备一系列的参数
    modality_rm_list = [self.first_modality_rm,self.second_modality_rm]
    modality_list = df[self.modality].unique() 
    print('modality_list:',modality_list)
    column_list = self.construct_column_list(modality_list)
    print('column_list:',column_list)
    subj_list = df[self.subj].unique()
    region_list = df[self.region].unique()
    x_data = np.arange(len(modality_list)) * spacing
    y_data = []  #需要在循环中给予赋值
    error_data = [] #需要在循环中给予赋值
    title = ''
   
    #下面是构造输出文件路径。
    svg_output_filepath = output_dirpath + os.sep + self.eponymous + self.dotsvg     
    print('svg_output_filepath:',svg_output_filepath)
    coeff_output_filepath = output_dirpath + os.sep + self.eponymous + self.coeff + self.dotxlsx
    coeff_mean_output_filepath = output_dirpath + os.sep + self.eponymous + self.coeff + self.underline + self.groupmean_coeff + self.underline + \
                                  self.groupmean_pvalue + self.underline + self.mean_std + self.dotxlsx
    #生成fig axe_array用于plot
    fig,axe_list = Figure_gridspec.gridspec(figsize_tuple,style)
    #构造一个df用于存放coeff值
    coeff_df = pd.DataFrame(index=subj_list,columns=column_list)
    coeff_mean_df = pd.DataFrame(index=[self.mean_std,self.groupmean_coeff,self.groupmean_pvalue],columns=modality_list)
    print('coeff_df:',coeff_df)
    print('coeff_mean_df:',coeff_mean_df)

    
    for modality_item in modality_list:
      print('modality_item:',modality_item)
      modality_item_df = df[df[self.modality]==modality_item]
      for subj_item in subj_list:
        print('subj_item:',subj_item)
        subj_modality_item_df = modality_item_df[modality_item_df[self.subj]==subj_item]
        
        #将每一个subject不同region的均值取出（两个modality各得一组数。）
        first_modality_rms = subj_modality_item_df[modality_rm_list[0]]
        second_modality_rms = subj_modality_item_df[modality_rm_list[1]]
        
        #求出pearson的相关系数及p值放在coeff_pvalue中，然后在分别放到coeff_df
        coeff_pvalue = pearsonr(first_modality_rms,second_modality_rms)
        coeff_df[modality_item+self.coeff][subj_item] = coeff_pvalue[0]
        coeff_df[modality_item+self.pvalue][subj_item] = coeff_pvalue[1]
      
      #下面求出coeff的均值和标准差
      mean = '%.2f'%coeff_df[modality_item+self.coeff].mean()
      std = '%.2f'%coeff_df[modality_item+self.coeff].std()
      coeff_mean_df[modality_item][self.mean_std] = mean + '±' + std
      y_data.append(float(mean))
      error_data.append(float(std))

    Axe_bar.axe(axe_list[3],x_data, y_data, error_data, self.x_label_str, self.y_label_str, title,\
             self.color_list,barwidth,self.error_color_list[0],modality_list,major_locator)
    
    y_data = []
    error_data = []
    title = self.title_str
    for modality_item in modality_list:
      print('modality_item:',modality_item)
      modality_item_df = df[df[self.modality]==modality_item]
      modality1groupmean_region_list = []
      modality2groupmean_region_list = []
      for region_item in region_list:
        region_modality_item_df = modality_item_df[modality_item_df[self.region]==region_item]
        modality1groupmean_region_list.append(region_modality_item_df[modality_rm_list[0]].mean())
        modality2groupmean_region_list.append(region_modality_item_df[modality_rm_list[1]].mean())
      coeff_pvalue = pearsonr(modality1groupmean_region_list,modality2groupmean_region_list)
      coeff_pvalue_str = '%.2f'%coeff_pvalue[0]
      coeff_mean_df[modality_item][self.groupmean_coeff] = coeff_pvalue_str
      coeff_mean_df[modality_item][self.groupmean_pvalue] = coeff_pvalue[1]
      y_data.append(float(coeff_pvalue_str))

      #如果是self.pet_falff，self.pet_reho，则散点图。
      if modality_item == self.pet_falff:
        agent_list = modality_item.split('vs')
        Axe_scatter.axe(axe_list[1],modality1groupmean_region_list,modality2groupmean_region_list,agent_list[0],agent_list[1],modality_item)
      if modality_item == self.pet_reho:
        agent_list = modality_item.split('vs')
        Axe_scatter.axe(axe_list[2],modality1groupmean_region_list,modality2groupmean_region_list,agent_list[0],agent_list[1],modality_item)
    
    Axe_bar.axe(axe_list[0],x_data, y_data, error_data, self.x_label_str, self.y_label_str, title,\
             self.color_list,barwidth,self.error_color_list[0],modality_list,major_locator)
    
    fig.savefig(svg_output_filepath,format=self.svg)
    coeff_df.to_excel(coeff_output_filepath)
    coeff_mean_df.to_excel(coeff_mean_output_filepath)
    
  construct_column_list = Basic_method.construct_column_list

#%%

class Across_subject_regionmean_summarize(Basic_const):
  
  x_label_str = ''
  y_label_str = 'Correlation'
  eponymous  = 'Across_subject_regionmean_summarize'
  
  across_subject_str = 'Across subject region-wise'
  def __init__(self,input_filepath,figsize_tuple,column_numb,barwidth,spacing,style,major_locator,output_dirpath):
    #
    df = pd.read_excel(input_filepath)
    
    #根据读取的df准备必要的参数
    modality_rm_list = [self.first_modality_rm,self.second_modality_rm]
    region_list = df[self.region].unique()
    axe_numb = len(region_list)
    modality_list = df[self.modality].unique()
    column_list = self.construct_column_list(region_list)
    x_data = np.arange(len(modality_list)) * spacing
    error_data = []  #在此处error_data是不需要的,设置成空的list即可。
    x_label = self.x_label_str
    y_label = self.y_label_str

    #下面是构造输出文件路径。
    svg_output_filepath = output_dirpath + os.sep + self.eponymous + self.dotsvg     
    print('svg_output_filepath:',svg_output_filepath)
    
    excel_output_filepath =  output_dirpath + os.sep + self.eponymous + self.dotxlsx
    print('excel_output_filepath:',excel_output_filepath)
    
    #生成fig axe_array用于plot
    fig,axe_array = Figure_multiaxe.multiaxe(figsize_tuple,axe_numb,column_numb,style)
    #构造一个df用于存放coeff pvalue值
    coeff_across_subject_regionwise_df = pd.DataFrame(index=modality_list,columns=column_list)

    #下面每一个region_item占一个axe，每一个modality_item占某一个axe内的一个bar
    i = 0
    for region_item in region_list:
      #下面将df属于region_item的那一部分取出
      region_item_df = df[df[self.region]==region_item]
      title = region_item
      y_data = []  #需要在循环中给予赋值
      #下面开始按照modality_item循环，以收集y_data和error_data
      j = 0
      for modality_item in modality_list:
        #agent是一个中间变量
        modality1_rm_nparray = region_item_df[region_item_df[self.modality]==modality_item][modality_rm_list[0]]
        modality2_rm_nparray = region_item_df[region_item_df[self.modality]==modality_item][modality_rm_list[1]]
        #计算modality1_rm_nparray,modality2_rm_nparray这两个nparray的Pearson coefficient
        coeff_pvalue = pearsonr(modality1_rm_nparray,modality2_rm_nparray)
        coeff = '%.2f'%coeff_pvalue[0]
        y_data.append(float(coeff))
        coeff_across_subject_regionwise_df[str(region_item)+self.coeff][modality_item] = coeff
        coeff_across_subject_regionwise_df[str(region_item)+self.pvalue][modality_item] = coeff_pvalue[1]
        j = j + 1

      Axe_bar.axe(axe_array[i][self.zero_numb],x_data, y_data, error_data, x_label, y_label, title,\
               self.color_list,barwidth,self.error_color_list[0],modality_list,major_locator)
      i = i + 1

    fig.savefig(svg_output_filepath,format=self.svg)
    coeff_across_subject_regionwise_df.to_excel(excel_output_filepath)
    
  construct_column_list = Basic_method.construct_column_list

#%%